use aqua::{convert::Responser, server::prelude::*};
use serde::{Deserialize, Serialize};
use crate::database::{self, Student};

#[derive(Responser, Serialize, Deserialize)]
enum StuError {
    #[response(status = 500, content_type = "json")]
    InternalError(String),

    #[response(status = 404, content_type = "json")]
    NoStudentFound,

    #[response(status = 409, content_type = "json")]
    AddStudentFailed(String),

    #[response(status = 410, content_type = "json")]
    ListStudentsFailed(String),
}

#[get(path = "/index")]
fn index() -> Result<Html<String>, ServerResourceError> {
    render_template("index.html")
}

#[get(path = "/api/student", query = "id")]
fn query_student(id: &str) -> Result<Json<Student>, StuError> {
    match database::fetch_student(id) {
        Result::Ok(Some(s)) => Result::Ok(Json(s)),
        Result::Ok(None) => Err(StuError::NoStudentFound),
        Result::Err(err) => Err(StuError::InternalError(err.to_string())),
    }
}

#[post(path = "/api/add_student", body = student)]
fn add_student(Json(student): Json<Student>) -> Result<(), StuError> {
    match database::insert_student(&student) {
        Ok(()) => Ok(()),
        Err(err) => Err(StuError::AddStudentFailed(err.to_string()))
    }
}

#[get(path = "/api/all_students")] 
fn all_students() -> Result<Json<Vec<Student>>, StuError> {
    match database::fetch_all_students() {
        Ok(v) => Ok(Json(v)),
        Err(err) => Err(StuError::ListStudentsFailed(err.to_string())),
    }
}